package org.springframework.mybatis.utils;

import org.springframework.annotation.mybatis.Mapper;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.mybatis.config.Configuration;
import org.springframework.mybatis.proxy.MapperProxy;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>MyBatis工具类，主要完成初始化JDBC环境，已经与IOC的接入工作</p>
 * @author Bosen
 * @date 2021/9/29 0:32
 */
public class MyBatisUtils {

    /**
     * <p>存储扫描出来的bean的全类名</p>
     */
    public static List<String> registryBeanClasses = new ArrayList<>();

    private static Configuration config;

    /**
     * <p>初始化JDBC环境</p>
     */
    public static void instantiationMyBatisConfig(String location) {
        config = new Configuration(location);
        JDBCUtils.init(config);
    }

    /**
     * <p>扫描mapper</p>
     */
    public static List<BeanDefinition> scanMapperBeanDefinition(List<BeanDefinition> beanDefinitions) throws Exception {
        List<BeanDefinition> mapperBeanDefinitions = new ArrayList<>();
        String mapperPackage = config.getMapperPackage();

        // 扫描mapper
        doScan(mapperPackage);

        for (String className : registryBeanClasses) {
            Class<?> mapper = Class.forName(className);
            if (!mapper.isAnnotationPresent(Mapper.class)) {
                // 如果不是mapper则跳过
                continue;
            }

            mapperBeanDefinitions.add(doCreateBeanDefinition(toLowerFirstCase(
                    mapper.getSimpleName()), mapper.getName()));;
        }
        // 合并
        beanDefinitions.addAll(mapperBeanDefinitions);
        return beanDefinitions;
    }

    /**
     * <p>将类信息转化为beanDefinition</p>
     */
    public static BeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName) {
        BeanDefinition beanDefinition = new BeanDefinition();
        beanDefinition.setBeanClassName(beanClassName);
        beanDefinition.setFactoryBeanName(factoryBeanName);
        return beanDefinition;
    }

    /**
     * <p>扫描包下的类</p>
     * @param scanPackage 包名
     */
    public static void doScan(String scanPackage) throws Exception {
        // 将包名转为文件路径
        URL url = MyBatisUtils.class.getResource("/" + scanPackage.replaceAll("\\.", "/"));
        if (url == null) {
            throw new Exception("包" + scanPackage + "不存在！");
        }
        File classPath = new File(url.getFile());
        for (File file : classPath.listFiles()) {
            if (file.isDirectory()) {
                doScan(scanPackage + "." +file.getName());
            } else {
                if (!file.getName().endsWith(".class")) {
                    // 如果不是class文件则跳过
                    continue;
                }
                String className = scanPackage + "." + file.getName().replace(".class", "");
                registryBeanClasses.add(className);
            }
        }
    }

    /**
     * <p>创建代理类</p>
     */
    public static MapperProxy createProxy(Class<?> mapperInterface) {
        return new MapperProxy(mapperInterface);
    }

    /**
     * <p>将类名首字母小写</p>
     */
    private static String toLowerFirstCase(String simpleName) {
        char[] chars = simpleName.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
}
